<template>
  <div class="content-wrap single-table-wrap">
    <div class="content-box">
      <div :class="{ 'content-left w0': collapseIconLeft, 'content-left': !collapseIconLeft }">
        <div class="filter-wrap">
          <Button size="small" type="info" @click="singleTableQueryBtnClickHandle">单表查询</Button>
          <Button size="small" type="primary" @click="userQueryBtnClickHandle">用户查询</Button>
          <Button size="small" type="warning" @click="tradeQueryBtnClickHandle">行业查询</Button>
        </div>
        <div class="table-wrap">
          <Table
            ref="table"
            class="table-item"
            :columns="tableColums"
            :loading="tableLoading"
            @on-row-click="tableClickHandle"
            size="small"
            :height="tableHeight"
            :data="tableData"
            :no-data-text="tableHint"
            highlight-row
          ></Table>
          <div class="page-box tc">
            <Page
              :total="tablePageData.total"
              :current="tablePageParams.pageNum"
              size="small"
              simple
              @on-change="changeTablePageHandle"
              :page-size="tablePageParams.pageSize"
            />
            <span class="reset-btn" title="重置" @click="restTableHandle">
              <Icon type="md-refresh-circle" />
            </span>
          </div>
        </div>
      </div>
      <div :class="centerClass">
        <div class="top-box">
          <Card :bordered="false">
            <div slot="title" class="tc card-head">
              <span class="collapse-left-icon collapse-icon" @click="collapseHandler('left')">
                <span v-if="collapseIconLeft" title="缩小">
                  <Icon type="icon iconfont icon-xianghou" />
                </span>
                <span v-else title="放大">
                  <Icon type="icon iconfont icon-xiangqian" />
                </span>
              </span>
              <Select
                v-model="indexFlag"
                style="width: 100px;"
                size="small"
                placeholder="指数类型"
                @on-change="changeIndexFlagHandle"
              >
                <Option v-for="item in filterCycle" :key="item.value" :value="item.value">{{ item.name }}</Option>
              </Select>
              <Button size="small" type="info" @click="indexHandle" style="margin-left:10px">指数平滑</Button>
              <Button size="small" type="primary" @click="xbwlsjHandle" style="margin-left:10px">小波神经网络</Button>
              <Button size="small" type="default" @click="greyTheoryModelHandle" style="margin-left:10px"
                >长期灰色理论模型</Button
              >
              <Button
                size="small"
                type="warning"
                @click="kxianBackHandle"
                v-show="showKxianBackBtn"
                style="margin-left:10px"
                >返回</Button
              >
              <span class="collapse-right-icon collapse-icon" @click="collapseHandler('right')">
                <span v-if="collapseIconRight" title="缩小">
                  <Icon type="icon iconfont icon-xiangqian" />
                </span>
                <span v-else title="放大">
                  <Icon type="icon iconfont icon-xianghou" />
                </span>
              </span>
            </div>
            <div class="chart-box">
              <candlestick
                id="single-table-candlestick"
                :chartData="candlestickData"
                :options="candlestickOptions"
                :collapseIcon="collapseIcon"
                @datazoom="candlestickDatazoom"
                @contextmenu="candlestickContextMenukHandle"
                @clickSeries="candlestickClickHandle"
              />
              <Spin fix v-show="kxianSpinLoading">加载中...</Spin>
            </div>
          </Card>
        </div>
        <div class="bottom-box">
          <Card :bordered="false">
            <div slot="title" class="clearfix">
              <span class="fl">折线图</span>
              <div class="fr">
                <Button @click="submitData" size="small" type="primary" style="margin-right:10px">提交修改</Button>
                <Button @click="saveData" size="small" type="info">保存</Button>
              </div>
            </div>
            <div class="chart-box">
              <echart-barline-marker
                id="single-table-zhexianday"
                :chartData="zhexianDayData"
                :options="zhexianDayOptions"
                :selectedPoints="zhexianSelectedPoints"
                :markPointData="currentMarkData"
                :collapseIcon="collapseIcon"
                @contextmenu="zhexianContextMenuSelectHandle"
                @clickSeries="zhexiantuClickHandle"
              />
              <Spin fix v-show="zhexianSpinLoading">加载中...</Spin>
            </div>
          </Card>
        </div>
      </div>
      <div :class="{ 'content-right w0': collapseIconRight, 'content-right': !collapseIconRight }">
        <div class="top-box">
          <Card :bordered="false">
            <div slot="title" class="clearfix">
              <span class="title-text">预测误差</span>
              <Select
                v-model="errorType"
                class="fr"
                style="width: 120px;"
                size="small"
                placeholder="误差类型"
                @on-change="changeErrorTypeHandle"
              >
                <Option value="perc">误差百分比</Option>
                <Option value="size">误差用气量</Option>
              </Select>
            </div>
            <div class="chart-box">
              <h-bar3d :defaultOptions="hBar3dOptions" :chartData="barlineData" />
              <Spin fix v-show="indexSpinLoading">加载中...</Spin>
              <span class="tips tc">{{ tipsText }}</span>
            </div>
          </Card>
        </div>
        <div class="bottom-box">
          <Card :bordered="false">
            <div slot="title">
              详情
            </div>
            <div class="detail-box">
              <meter-detail
                :currentMeterId="currentMeterId"
                :content="meterDetail"
                :columnNames="meterDetailColumns"
                :currentDate="currentDate"
              />
            </div>
          </Card>
        </div>
      </div>

      <!-- 单表查询 -->
      <Modal
        class="single-table-modal"
        v-model="singleTableQueryModelFlag"
        title="单表查询"
        width="360"
        @on-cancel="handleModalCancel"
      >
        <Form :model="sigleTaleQueryFormData" label-position="top" @submit.native.prevent="singleTableQueryHandle">
          <FormItem label="表号">
            <Input v-model="sigleTaleQueryFormData.meterId" ref="meterId" placeholder="请输入表号" />
          </FormItem>
        </Form>
        <div slot="footer">
          <Button type="primary" @click="singleTableQueryHandle">查询</Button>
        </div>
      </Modal>
      <!-- 用户查询 -->
      <Modal
        class="single-table-modal"
        v-model="userQueryModelFlag"
        title="用户查询"
        width="360"
        @on-cancel="handleModalCancel"
      >
        <Form :model="userQueryFormData" label-position="top">
          <FormItem label="用户编号">
            <Input v-model="userQueryFormData.unitId" placeholder="请输入用户编号" />
          </FormItem>
          <FormItem label="用户名称">
            <Input v-model="userQueryFormData.unitName" placeholder="请输入用户名称" />
          </FormItem>
        </Form>
        <div slot="footer">
          <Button type="primary" @click="userQueryHandle">查询</Button>
        </div>
      </Modal>

      <!-- 行业查询 -->
      <Modal
        v-model="tradeQueryModelFlag"
        title="行业查询"
        width="96%"
        @on-cancel="handleModalCancel"
        :styles="{ top: '30px', height: '85%' }"
      >
        <div
          :is="tradeQueryTemplate"
          :fetchData="fetchRectTreeMapData"
          :chartData="treemapData"
          @q-click="rectTreeMapClickHandle"
        ></div>
      </Modal>

      <!-- 指数平滑 -->
      <Modal
        class="single-table-modal"
        v-model="indexModelFlag"
        title="指数平滑"
        width="360"
        @on-cancel="handleModalCancel"
      >
        <Form
          ref="indexForm"
          :model="indexFormData"
          :rules="indexFormRuleValidate"
          label-position="top"
          @submit.native.prevent="indexQueryHandle"
        >
          <FormItem label="平滑天数" prop="days">
            <InputNumber v-model="indexFormData.days" :min="0" placeholder="请输入平滑天数" style="width:100%" />
          </FormItem>
          <FormItem label="预测天数" prop="predictDays">
            <InputNumber v-model="indexFormData.predictDays" :min="0" placeholder="请输入平滑天数" style="width:100%" />
          </FormItem>
        </Form>

        <div slot="footer">
          <Button type="primary" @click="indexQueryHandle('indexForm')">查询</Button>
        </div>
      </Modal>

      <!-- 小波神经网络 -->
      <Modal
        class="single-table-modal"
        v-model="xbwlsjModelFlag"
        title="小波神经网络"
        width="360"
        @on-cancel="handleModalCancel"
      >
        <Form
          ref="xbwlsjForm"
          :model="xbwlsjFormData"
          :rules="xbwlsjFormRuleValidate"
          label-position="top"
          @submit.native.prevent="xbwlsjQueryHandle"
        >
          <FormItem label="天数" prop="days">
            <InputNumber v-model="xbwlsjFormData.days" :min="0" placeholder="请输入天数" style="width:100%" />
          </FormItem>
          <FormItem label="预测天数" prop="predictDays">
            <InputNumber v-model="xbwlsjFormData.predictDays" :min="0" placeholder="请输入天数" style="width:100%" />
          </FormItem>
          <FormItem label="训练轮数" prop="maxTime">
            <InputNumber v-model="xbwlsjFormData.maxTime" :min="0" placeholder="请输入轮数" style="width:100%" />
          </FormItem>
          <FormItem label="关联天数" prop="associatedDays">
            <InputNumber v-model="xbwlsjFormData.associatedDays" :min="0" placeholder="请输入天数" style="width:100%" />
          </FormItem>
        </Form>

        <div slot="footer">
          <Button type="primary" @click="xbwlsjQueryHandle('xbwlsjForm')">查询</Button>
        </div>
      </Modal>

      <!-- 长期灰色理论模型 -->
      <Modal
        class="single-table-modal"
        v-model="greyTheoryModelFlag"
        title="长期灰色理论模型"
        width="360"
        @on-cancel="handleModalCancel"
      >
        <Form
          ref="greyTheoryModelForm"
          :model="greyTheoryModelFormData"
          :rules="greyTheoryModelFormRuleValidate"
          label-position="top"
          @submit.native.prevent="greyTheoryModelQueryHandle"
        >
          <FormItem label="预测天数" prop="predictDays">
            <InputNumber
              v-model="greyTheoryModelFormData.predictDays"
              :min="0"
              placeholder="请输入天数"
              style="width:100%"
            />
          </FormItem>
        </Form>

        <div slot="footer">
          <Button type="primary" @click="greyTheoryModelQueryHandle('greyTheoryModelForm')">查询</Button>
        </div>
      </Modal>
    </div>
  </div>
</template>
<script>
import echarts from 'echarts'
import {
  each,
  last,
  concat,
  isUndefined,
  isEmpty,
  includes,
  filter,
  uniq,
  reverse,
  cloneDeep,
  indexOf,
  difference,
  merge,
  findIndex,
  isArray,
  isEqual
} from 'lodash'
import dayjs from 'dayjs'
import tableColums from './tableColums'
import {
  tableData,
  rectTreeMap,
  getMeterDetailData,
  zhishupinghuaData,
  xbwlsj,
  kxianDataByIndexType,
  kxianDataByDys,
  greyTheoryModel,
  submitData,
  getZhexianByDay
} from '@/api/singleTable'
import setTableHeightMixin from '@/mixins/setTableHeight'
import tableKeyUpToolMixin from '@/mixins/tableKeyUpTool'
import { hBar3dOptions, eTreemapOptions, zhexianDayOptions, candlestickOptions } from './chartOptions/index'
import meterDetailColumns from './meterDetailColumns'

const filterCycle = Object.freeze([
  {
    name: '日',
    value: 'day'
  },
  {
    name: '周',
    value: 'week'
  },
  {
    name: '月',
    value: 'month'
  }
])

const markItemStyle = {
  itemStyle: {
    color: '#c23531'
  },
  label: {
    formatter: function(val) {
      return val.name
    }
  }
}

export default {
  name: '',
  mixins: [setTableHeightMixin, tableKeyUpToolMixin],
  components: {
    MeterDetail: () => import('@/commons/MeterDetail'),
    ETreemap: () => import('@/commons/charts/ETreemap'),
    EchartBarlineMarker: () => import('@/commons/charts/EchartBarlineMarker'),
    Candlestick: () => import('@/commons/charts/Candlestick'),
    HBar3d: () => import('@/commons/charts/HBar3d')
  },
  data() {
    return {
      tableColums: tableColums,
      tableLoading: false,
      tableData: [],
      tableHint: '',
      tablePageParams: {
        pageNum: 1,
        pageSize: 20
      },
      tablePageData: {
        total: 0
      },
      hasMoveFlag: false,
      kxianSpinLoading: false,
      zhexianSpinLoading: false,
      indexSpinLoading: false,
      currentMeterGasClass: undefined,
      indexFlag: 'day',
      singleTableQueryModelFlag: false, // 控制单表查询模态框显示、隐藏
      userQueryModelFlag: false, // 用户查询模态框显示、隐藏
      tradeQueryModelFlag: false, // 行业查询模态框显示、隐藏
      indexModelFlag: false, // 平均指数模态框显示、隐藏
      sigleTaleQueryFormData: {
        meterId: undefined
      },
      resultSubmitData: [],
      userQueryFormData: {
        unitId: undefined,
        unitName: undefined
      },
      indexFormData: {
        days: 30,
        predictDays: 1
      },
      indexFormRuleValidate: {
        days: [
          { type: 'number', required: true, message: '天数不能为空', trigger: 'blur' },
          { type: 'number', min: 1, message: '不能小于1天', trigger: 'blur' }
        ],
        predictDays: [
          { type: 'number', required: true, message: '天数不能为空', trigger: 'blur' },
          { type: 'number', min: 1, message: '不能小于1天', trigger: 'blur' }
        ]
      },
      greyTheoryModelFormData: {
        predictDays: 1
      },
      greyTheoryModelFormRuleValidate: {
        predictDays: [
          { type: 'number', required: true, message: '天数不能为空', trigger: 'blur' },
          { type: 'number', min: 1, message: '不能小于1天', trigger: 'blur' }
        ]
      },
      showDetailLoading: false,
      tradeQueryTemplate: null,
      meterDetail: {},
      treemapData: null,
      zhexianDayData: null,
      currentMarkData: [],
      currentMeterId: undefined,
      candlestickData: {},
      echartsLineData: null,
      echartsXAxisData: [],
      currentMonth: null,
      hasZhishuRequest: true,
      zhexianSelectedPoints: null,
      zhexianKeyUpSelecteIndex: 0,
      zhexiantuFinishedStatus: false,
      zhexiantuHasSelected: false,
      collapseIconRight: false,
      collapseIconLeft: false,
      collapseIcon: false,
      xbwlsjModelFlag: false,
      xbwlsjFormData: {
        days: 30,
        predictDays: 1,
        maxTime: 50,
        associatedDays: 4
      },
      xbwlsjFormRuleValidate: {
        days: [
          { type: 'number', required: true, message: '天数不能为空', trigger: 'blur' },
          { type: 'number', min: 1, message: '不能小于1天', trigger: 'blur' }
        ],
        predictDays: [
          { type: 'number', required: true, message: '天数不能为空', trigger: 'blur' },
          { type: 'number', min: 1, message: '不能小于1天', trigger: 'blur' }
        ],
        maxTime: [
          { type: 'number', required: true, message: '轮数不能为空', trigger: 'blur' },
          { type: 'number', min: 1, message: '不能小于1轮', trigger: 'blur' }
        ],
        associatedDays: [
          { type: 'number', required: true, message: '天数不能为空', trigger: 'blur' },
          { type: 'number', min: 1, message: '不能小于1天', trigger: 'blur' }
        ]
      },
      errorType: 'perc',
      errorData: null,
      barlineData: null,
      indexHasCandlestickDatezoom: true,
      datezoomRangeByIndex: [],
      showKxianBackBtn: false,
      currentKxianReqIndexType: null,
      renderedFlag: false,
      greyTheoryModelFlag: false
    }
  },
  computed: {
    defaultDate() {
      return this.$config.nowDate
    },
    zhexianDayOptions() {
      return zhexianDayOptions
    },
    candlestickOptions() {
      return candlestickOptions
    },
    hBar3dOptions() {
      return hBar3dOptions
    },
    tipsText() {
      return this.errorType === 'perc' ? '百分比(%)' : '用气量(方)'
    },
    filterCycle() {
      return filterCycle
    },
    meterDetailColumns() {
      return meterDetailColumns
    },
    currentDate() {
      return dayjs(this.defaultDate).format('YYYY-MM')
    },
    centerClass() {
      let _cls = 'content-center'
      if (this.collapseIconLeft) {
        _cls += ' l0'
      }
      if (this.collapseIconRight) {
        _cls += ' r0'
      }
      return _cls
    }
  },
  mounted() {
    this.fetchTableData()
    this.currentKxianReqIndexType = this.indexFlag
  },
  watch: {
    /**
     * desc: 表格数据变化，初始化对应数据
     * param {type}
     * return:
     */
    tableData(newData, oldData) {
      if (!isEqual(newData, oldData)) {
        this.removeEvent()
        this.indexHasCandlestickDatezoom = true
        this.meterDetail = {}
        this.showKxianBackBtn = false
        this.barlineData = null
        this.zhexianDayData = null
        this.candlestickData = {}
        this.selectedIndex = undefined
        this.currentMeterId = undefined
      }
    }
  },
  methods: {
    showWraningNotice(title = undefined, desc) {
      this.$Notice.warning({
        title: title || '操作提示',
        desc
      })
    },
    /**
     * @msg: 显示加载
     * @param {type}
     * @return:
     */
    showLoading() {
      this.$Spin.show({
        render: h => {
          return h('div', [
            h('Icon', {
              class: 'spin-icon-load',
              props: {
                type: 'ios-loading',
                size: 20
              }
            }),
            h('div', '图表生成中...')
          ])
        }
      })
    },
    /**
     * @name: hideLoading
     * @test: test font
     * @msg: 隐藏loading
     * @param {type}
     * @return:
     */
    hideLoading() {
      this.$Spin.hide()
    },
    /**
     * @msg: 显示模态框，阻止页面键盘事件
     * @param {type}
     * @return:
     */
    handleModalCancel() {
      this.hasMoveFlag = false
    },
    /**
     * @msg: 翻页操作
     * @param {type}
     * @return:
     */
    changeTablePageHandle(data) {
      this.tablePageParams = {
        ...this.tablePageParams,
        pageNum: data
      }
      this.$nextTick(() => {
        this.fetchTableData()
      })
    },
    /**
     * @msg: 表格行点击
     * @param {type}
     * @return:
     */
    tableClickHandle(row = {}, index) {
      if (isUndefined(this.selectedIndex)) {
        this.dispatchEvent()
      }
      if (this.selectedIndex !== index) {
        this.selectedIndex = index
        if (!isEmpty(this.candlestickData)) {
          this.candlestickData = {}
        }
        this.showKxianBackBtn = false
        this.currentKxianReqIndexType = this.indexFlag
        this.$nextTick(() => {
          this.currentSelectedTableData()
        })
      }
    },
    /**
     * @msg: 选取当前选中的数据项,并请求折线图数据
     * @param {type}
     * @return:
     */
    currentSelectedTableData() {
      if (!isEmpty(this.candlestickData)) {
        this.candlestickData = {}
      }
      const currentData = this.tableData[this.selectedIndex]
      this.selectedData = currentData
      const { meterId } = currentData
      this.currentMeterId = meterId
      const retMonth = dayjs(this.defaultDate).format('YYYY-MM')
      this.currentMonth = retMonth
      this.fetchMeterDetail(meterId)
      this.fetchZhexianByDayData({ meterId })
      this.fetchDataByIndexType({
        meterId,
        month: retMonth,
        type: this.indexFlag
      })
    },
    /**
     * @msg: 点击单表查询按钮
     * @param {type}
     * @return:
     */
    singleTableQueryBtnClickHandle() {
      this.singleTableQueryModelFlag = true
      this.hasMoveFlag = true
      this.$nextTick(() => {
        this.$refs['meterId'].focus()
      })
    },
    /**
     * @msg: 点击用户查询按钮
     * @param {type}
     * @return:
     */
    userQueryBtnClickHandle() {
      this.userQueryModelFlag = true
      this.hasMoveFlag = true
    },
    /**
     * @msg: 行业查询
     * @param {type}
     * @return:
     */
    tradeQueryBtnClickHandle() {
      this.tradeQueryModelFlag = true
      this.hasMoveFlag = true
      this.tradeQueryTemplate = 'ETreemap'
    },
    /**
     * @msg: 点击指数平滑
     * @param {type}
     * @return:
     */
    indexHandle() {
      const { currentMeterId } = this
      if (!currentMeterId) {
        return this.showWraningNotice('', '请选择数据后再操作')
      }
      if (this.showKxianBackBtn) {
        return this.showWraningNotice('', '当前状态不能这样操作')
      }
      this.hasMoveFlag = true
      this.indexModelFlag = true
    },
    /**
     * @msg: 长期灰色理论模型
     * @param {type}
     * @return:
     */
    greyTheoryModelHandle() {
      const { currentMeterId } = this
      if (!currentMeterId) {
        return this.showWraningNotice('', '请选择数据后再操作')
      }
      this.hasMoveFlag = true
      this.greyTheoryModelFlag = true
    },
    /**
     * @msg: 获取表格数据
     * @param {type}
     * @return:
     */
    fetchTableData() {
      this.tableLoading = true
      tableData({
        ...this.tablePageParams,
        ...this.userQueryFormData,
        ...this.sigleTaleQueryFormData,
        meterGasClass: this.currentMeterGasClass
      })
        .then(res => {
          if (res.date && res.date.list) {
            const { total, list, pageNum, pageSize } = res.date
            this.tablePageParams = {
              ...this.tablePageParams,
              pageNum,
              pageSize
            }
            this.tablePageData = {
              ...this.tablePageData,
              total
            }
            this.tableData = list
            this.$nextTick(() => {
              this.setTableHeight()
            })
          }
          this.tableLoading = false
        })
        .catch(() => {
          this.tableHint = '暂无数据'
          this.tableLoading = false
        })
    },
    /**
     * @msg: 单表查询
     * @param {type}
     * @return:
     */
    singleTableQueryHandle() {
      this.fetchTableData()
      this.singleTableQueryModelFlag = false
      this.hasMoveFlag = false
    },
    /**
     * @msg: 用户查询
     * @param {type}
     * @return:
     */
    userQueryHandle() {
      this.fetchTableData()
      this.userQueryModelFlag = false
      this.hasMoveFlag = false
    },
    /**
     * @msg: 整理矩形树图数据
     * @param {type}
     * @return:
     */
    modifyTreemapData(data = []) {
      const _serList = []
      each(data, item => {
        const { count, meterGasClass } = item
        _serList.push({
          name: meterGasClass,
          value: count
        })
      })

      this.treemapData = merge({}, eTreemapOptions, {
        series: [
          {
            data: _serList
          }
        ]
      })
    },
    /**
     * @msg: 获取矩形树图数据
     * @param {type}
     * @return:
     */

    fetchRectTreeMapData() {
      rectTreeMap().then(res => {
        if (res.date) {
          this.modifyTreemapData(res.date)
        }
      })
    },
    /**
     * @msg: 方块图表点击
     * @param {type}
     * @return:
     */
    rectTreeMapClickHandle(params = {}) {
      const { data = {} } = params
      const { name } = data
      this.currentMeterGasClass = name
      this.tradeQueryModelFlag = false
      this.hasMoveFlag = false
      this.tablePageParams = {
        ...this.tablePageParams,
        pageNum: 1
      }
      this.tablePageData.total = 0
      this.selectedIndex = undefined
      this.$nextTick(() => {
        this.fetchTableData()
      })
    },
    /**
     * @msg: 重置表格数据
     * @param {type}
     * @return:
     */
    restTableHandle() {
      this.userQueryFormData = {
        unitId: undefined,
        unitName: undefined
      }
      this.sigleTaleQueryFormData = {
        meterId: undefined
      }
      this.currentMeterGasClass = undefined
      this.tablePageParams = {
        pageNum: 1,
        pageSize: 20
      }
      this.$nextTick(() => {
        this.fetchTableData()
      })
    },
    /**
     * @msg: 获取表具详情
     * @param {type}
     * @return:
     */
    fetchMeterDetail(meterId) {
      getMeterDetailData(meterId).then(res => {
        if (res.date) {
          this.meterDetail = res.date
        } else {
          this.meterDetail = null
        }
      })
    },
    /**
     * @msg: 整理一天折线图数据
     * @param {type}
     * @return:
     */
    modifyZhexianByDayData(data) {
      const filterMarkData = this.filterMarkData()
      const retArr = []
      const xAxisData = []
      let markData = []
      each(data, (item, index) => {
        const { hour, usage, mark } = item
        retArr.push({
          name: hour,
          value: usage,
          hour,
          mark,
          index
        })
        xAxisData.push(hour)
        if (mark && markData.length < 2) {
          let type = 'min'
          let name = '开始'
          if (markData.length !== 0) {
            type = 'max'
            name = '结束'
          }
          markData.push({
            ...markItemStyle,
            type,
            name,
            hour,
            index: hour - 1,
            coord: [hour - 1, usage],
            value: usage
          })
        }
      })
      this.zhexianDayData = {
        seriesData: retArr,
        xAxisData
      }

      this.showMeterDayModel = true

      this.currentMarkData = filterMarkData || markData
    },
    /**
     * @msg: 获取一天的折线图数据
     * @param {type}
     * @return:
     */
    fetchZhexianByDayData(params) {
      this.zhexianSpinLoading = true
      this.zhexiantuFinishedStatus = false
      this.zhexiantuHasSelected = false
      this.zhexianSelectedPoints = null
      this.zhexianKeyUpSelecteIndex = 0
      getZhexianByDay(params)
        .then(res => {
          this.zhexianSpinLoading = false
          if (res.date) {
            this.modifyZhexianByDayData(res.date)
          }
        })
        .catch(() => {
          this.zhexianSpinLoading = false
        })
    },
    /**
     * @msg: 指数图数据
     * @param {type}
     * @return:
     */
    modifyKxianData(rawData = [], type) {
      let categoryData = []
      let values = []
      const actualGas = []
      const markPointData = []
      each(rawData, item => {
        const [first, one, two, three, four, five] = item
        categoryData.push(first)
        let color0 = '#ec0000'
        let borderColor0 = '#8A0000'
        let color = '#00da3c'
        let borderColor = '#008F28'
        const lastItem = last(item)
        if (lastItem) {
          color0 = '#ff9900'
          borderColor0 = '#ff9900'
          color = '#ff9900'
          borderColor = '#ff9900'
          markPointData.push({
            name: first,
            value: two,
            type,
            coord: [first, two],
            itemStyle: {
              color: '#ff9900'
            }
          })
        }
        if (five < 0) {
          color0 = '#ed141e'
          borderColor0 = '#ed141e'
          color = '#ed141e'
          borderColor = '#ed141e'
        }
        values.push({
          name: first,
          value: [one, two, four, three],
          type,
          itemStyle: {
            color,
            borderColor,
            borderColor0,
            color0
          }
        })
        actualGas.push({
          name: first,
          value: five,
          type
        })
      })

      return {
        categoryData: categoryData,
        values: {
          data: values,
          markPointData
        },
        actualGas
      }
    },
    filterOtherSeriesData() {
      const { otherSeiesData } = this.candlestickData
      const newArr = filter(otherSeiesData, item => {
        return !includes(['下限值', '预测值', '上限值', '指数平滑', '小波神经网络预测', '预测区域'], item.name)
      })

      return newArr
    },
    /**
     * desc: 当查询了长期灰色理论模型，进行小波或者指数查询时需要清除灰色理论模型的数据
     * param {type}
     * return:
     */
    fileterSeriesData() {
      const { values, actualGas } = this.candlestickData
      const { data, markPointData } = values
      const _otherCates = []
      const _newData = []
      const _cateList = []
      each(data, item => {
        if (item.type === 'greyThory') {
          _otherCates.push(item.name)
        } else {
          _newData.push(item)
        }
      })
      const _newMarkPoint = filter(markPointData, item => {
        return item.type !== 'greyThory'
      })
      const _newActualGas = filter(actualGas, item => {
        return item.type !== 'greyThory'
      })
      each(data, item => {
        const { name } = item
        _cateList.push(name)
      })
      const _newCate = difference(_cateList, _otherCates)
      return {
        categoryData: _newCate,
        values: {
          data: _newData,
          markPointData: _newMarkPoint
        },
        actualGas: _newActualGas
      }
    },
    /**
     * @msg: 预测数据整理
     * @param {type}
     * @return:
     */
    modifyYuceData(data = {}, name) {
      const { forecast = [], matching = [] } = data
      const seriesData = []
      const matchLast = last(matching)
      const listFirstData = {
        name: matchLast.tId,
        value: [matchLast.tId, matchLast.value]
      }
      const topList = []
      const bottomList = []
      const midList = []
      each(forecast, item => {
        const { tId, value = [] } = item
        topList.push({
          name: tId,
          value: [tId, value[2]],
          itemStyle: {
            color: '#d53a35'
          }
        })
        bottomList.push({
          name: tId,
          value: [tId, value[0]]
        })
        midList.push({
          name: tId,
          value: [tId, value[1]]
        })
      })
      each(matching, item => {
        seriesData.push({
          name: item.tId,
          value: [item.tId, item.value]
        })
      })

      const newArr = this.filterOtherSeriesData()
      const newBottomList = cloneDeep(bottomList)
      const analysisAreaData = concat(listFirstData, topList, reverse(newBottomList))
      // 去除长期灰色理论模型数据
      const { categoryData = [], values, actualGas } = this.fileterSeriesData()
      const _newCateList = []
      each(analysisAreaData, item => {
        const { name } = item
        if (!includes(_newCateList, name)) {
          _newCateList.push(name)
        }
      })
      this.candlestickData = {
        ...this.candlestickData,
        categoryData: uniq(concat(categoryData, _newCateList)),
        actualGas,
        values,
        otherSeiesData: concat(
          newArr,
          {
            yAxisIndex: 1,
            name,
            smooth: true,
            type: 'line',
            data: seriesData
          },
          {
            type: 'custom',
            name: '预测区域',
            yAxisIndex: 1,
            smooth: true,
            renderItem: this.kxianRenderArea(analysisAreaData),
            data: analysisAreaData
          },
          {
            type: 'line',
            name: '上限值',
            yAxisIndex: 1,
            data: concat(listFirstData, topList),
            itemStyle: {
              color: '#d53a35'
            }
          },
          {
            type: 'line',
            name: '预测值',
            yAxisIndex: 1,
            data: concat(listFirstData, midList),
            itemStyle: {
              color: '#0035f9'
            }
          },
          {
            type: 'line',
            name: '下限值',
            yAxisIndex: 1,
            data: concat(listFirstData, bottomList),
            itemStyle: {
              color: '#d53a35'
            }
          }
        )
      }
    },
    /**
     * @msg: 预测区域绘制
     * @param {type}
     * @return:
     */
    kxianRenderArea(data = []) {
      return (params, api) => {
        if (params.context.rendered) {
          return
        }
        params.context.rendered = true
        const points = []
        for (let i = 0; i < data.length; i++) {
          points.push(api.coord(data[i].value))
        }
        const color = '#d53a35'

        return {
          type: 'polygon',
          shape: {
            points: echarts.graphic.clipPointsByRect(points, {
              x: params.coordSys.x,
              y: params.coordSys.y,
              width: params.coordSys.width,
              height: params.coordSys.height
            })
          },
          style: api.style({
            fill: color,
            stroke: echarts.color.lift(color)
          })
        }
      }
    },
    /**
     * @msg: 整理指数平滑数据
     * @param {type}
     * @return:
     */
    modifyZhishupinghuaData(data = {}) {
      this.modifyYuceData(data, '指数平滑')
    },
    /**
     * @msg: 指数平滑查询
     * @param {type}
     * @return:
     */
    indexQueryHandle(name) {
      this.$refs[name].validate(valid => {
        if (valid) {
          this.indexModelFlag = false
          this.hasMoveFlag = false
          const { currentMeterId } = this
          this.kxianSpinLoading = true
          zhishupinghuaData({
            meterId: currentMeterId,
            type: this.indexFlag,
            ...this.indexFormData
          })
            .then(res => {
              this.indexSpinLoading = false
              this.kxianSpinLoading = false
              if (res.date && res.code === 200) {
                const { errorList = [], errorRateList = [] } = res.date
                this.errorData = {
                  errorList,
                  errorRateList
                }
                this.modifyZhishupinghuaData(res.date)
                this.$nextTick(() => {
                  this.modifyBarlineData()
                })
              } else {
                this.$Message.error(res.msg)
              }
            })
            .catch(() => {
              this.indexSpinLoading = false
              this.kxianSpinLoading = false
            })
        }
      })
    },
    /**
     * desc: 长期灰色理论模型数据整理
     * param {type}
     * return:
     */
    modifyGreyTheoryModelData(rawData = []) {
      const { categoryData, values = {}, actualGas } = this.modifyKxianData(rawData, 'greyThory')
      const {
        values: { data }
      } = this.candlestickData
      const _cateList = []
      each(data, item => {
        const { name } = item
        _cateList.push(name)
      })
      // 长期灰色理论模型数据添加特殊颜色进行区分
      values.data[0].itemStyle.color = '#2d8cf0'
      values.data[0].itemStyle.color0 = '#2a0ef6'
      // 这里是追加，和滚动加载数据刚好相反
      this.candlestickData = {
        ...this.candlestickData,
        categoryData: uniq(concat(_cateList || [], categoryData)),
        values: {
          data: concat(this.candlestickData.values ? this.candlestickData.values.data : [], values.data),
          markPointData: concat(
            this.candlestickData.values ? this.candlestickData.values.markPointData : [],
            values.markPointData
          )
        },
        actualGas: concat(this.candlestickData.actualGas || [], actualGas),
        otherSeiesData: []
      }
    },
    /**
     * @msg: 指数平滑查询
     * @param {type}
     * @return:
     */
    greyTheoryModelQueryHandle(name) {
      this.$refs[name].validate(valid => {
        if (valid) {
          this.greyTheoryModelFlag = false
          this.hasMoveFlag = false
          const { currentMeterId } = this
          this.kxianSpinLoading = true
          greyTheoryModel({
            meterId: currentMeterId,
            type: this.indexFlag,
            ...this.greyTheoryModelFormData
          })
            .then(res => {
              this.kxianSpinLoading = false
              if (res.date && res.code === 200) {
                this.modifyGreyTheoryModelData(res.date)
              } else {
                this.$Message.error(res.msg)
              }
            })
            .catch(() => {
              this.kxianSpinLoading = false
            })
        }
      })
    },
    /**
     * description: k线图缩放时数据整理
     * param {type}
     * return:
     */
    filterCandlestickData(data = []) {
      const { categoryData, values = {}, actualGas } = this.modifyKxianData(data)
      this.candlestickData = {
        ...this.candlestickData,
        categoryData: concat(categoryData, this.candlestickData.categoryData || []),
        values: {
          data: concat(values.data, this.candlestickData.values ? this.candlestickData.values.data : []),
          markPointData: concat(
            values.markPointData,
            this.candlestickData.values ? this.candlestickData.values.markPointData : []
          )
        },
        actualGas: concat(actualGas, this.candlestickData.actualGas || [])
      }
    },
    /**
     * @msg: 指数图缩放
     * @param {type}
     * @return:
     */
    candlestickDatazoom(data, chart) {
      if (!this.hasZhishuRequest) return
      // 指数类型为月份和周的时候取消滚动请求
      if (!this.indexHasCandlestickDatezoom) return
      const { batch } = data
      if (batch[0].start === 0 && batch[0].end === 100) {
        let retMonth = null
        if (includes(['week', 'month'], this.indexFlag)) {
          const index = indexOf(this.datezoomRangeByIndex, this.currentMonth)
          if (index === 0) return
          retMonth = this.datezoomRangeByIndex[index - 1]
        } else {
          retMonth = dayjs(this.currentMonth)
            .subtract(1, 'month')
            .format('YYYY-MM')
        }

        this.currentMonth = retMonth
        this.$nextTick(() => {
          const { currentMeterId } = this
          this.fetcKxianDaysData(
            {
              meterId: currentMeterId,
              date: retMonth,
              type: this.indexFlag === 'day' ? 'month' : this.indexFlag
            },
            'zoom'
          )
        })
      }
    },
    /**
     * @msg: 键盘操作折线图
     * @param {type}
     * @return:
     */
    keyUpSetZhexianData(type) {
      const { seriesData = [] } = this.zhexianDayData
      const sData = seriesData[this.zhexianKeyUpSelecteIndex]
      const selectData = {
        ...sData,
        index: sData.name - 1
      }
      this.zhexianContextMenuSelectHandle(selectData, type)
    },
    /**
     * @name: getZhexianSelectedPoint
     * @test: test font
     * @msg: 帅选出折线图点击点
     * @param {type}
     * @return:
     */
    getZhexianSelectedPoint() {
      this.$nextTick(() => {
        const { seriesData = [] } = this.zhexianDayData
        const selecteData = seriesData[this.zhexianKeyUpSelecteIndex]
        const { name, value } = selecteData
        const retData = {
          ...selecteData,
          value: [name - 1, value]
        }
        this.zhexianSelectedPoints = [
          {
            data: [retData],
            type: 'effectScatter'
          }
        ]
      })
    },
    /**
     * @msg: 折线图点击
     * @param {type}
     * @return:
     */
    zhexiantuClickHandle(params = {}) {
      this.zhexiantuFinishedStatus = true
      this.zhexiantuHasSelected = true
      const { data } = params
      const { index } = data
      this.zhexianKeyUpSelecteIndex = index
      this.getZhexianSelectedPoint()
    },
    /**
     * @msg: 两侧收缩中间放大
     * @param {type}
     * @return:
     */
    collapseHandler(type) {
      const { collapseIconLeft, collapseIconRight, collapseIcon } = this
      if (type === 'left') {
        this.collapseIconLeft = !collapseIconLeft
      } else {
        this.collapseIconRight = !collapseIconRight
      }
      this.collapseIcon = !collapseIcon
    },
    /**
     * @msg: 小波神经网络按钮点击
     * @param {type}
     * @return:
     */
    xbwlsjHandle() {
      const { currentMeterId } = this
      if (!currentMeterId) {
        return this.showWraningNotice('', '请选择数据后再操作')
      }
      if (this.showKxianBackBtn) {
        return this.showWraningNotice('', '当前状态不能这样操作')
      }
      this.hasMoveFlag = true
      this.xbwlsjModelFlag = true
    },
    /**
     * @msg: 小波神经网络数据整理
     * @param {type}
     * @return:
     */
    modifyXbwlsjQueryData(data = {}) {
      this.modifyYuceData(data, '小波神经网络预测')
    },
    /**
     * @msg: 小波神经网络数据获取
     * @param {type}
     * @return:
     */
    xbwlsjQueryHandle(name) {
      this.$refs[name].validate(valid => {
        if (valid) {
          const { currentMeterId } = this
          this.xbwlsjModelFlag = false
          this.hasMoveFlag = false
          this.kxianSpinLoading = true
          xbwlsj({
            meterId: currentMeterId,
            type: this.indexFlag,
            ...this.xbwlsjFormData
          })
            .then(res => {
              this.kxianSpinLoading = false
              if (res.date && res.code === 200) {
                const { errorList = [], errorRateList = [] } = res.date
                this.errorData = {
                  errorList,
                  errorRateList
                }
                this.modifyXbwlsjQueryData(res.date)
                this.$nextTick(() => {
                  this.modifyBarlineData()
                })
              } else {
                this.$Message.error(res.msg)
              }
            })
            .catch(() => {
              this.kxianSpinLoading = false
            })
        }
      })
    },
    /**
     * @msg: 柱状图数据处理
     * @param {type}
     * @return:
     */
    modifyBarlineData() {
      const _xAixsList = []
      const _serList = []
      let currentData = []
      const { errorList, errorRateList } = this.errorData
      if (this.errorType === 'perc') {
        currentData = errorRateList
      } else {
        currentData = errorList
      }
      each(currentData, item => {
        const { name, value } = item
        _xAixsList.push(name)
        _serList.push({
          name,
          y: value,
          type: this.errorType
        })
      })

      this.barlineData = merge({}, hBar3dOptions, {
        xAxis: {
          categories: _xAixsList
        },
        series: [
          {
            data: _serList
          }
        ]
      })
    },
    /**
     * @msg: 误差分析下拉框切换
     * @param {type}
     * @return:
     */
    changeErrorTypeHandle() {
      if (isEmpty(this.errorData)) {
        this.errorType = 'perc'
        return this.showWraningNotice('', '没有课操作的数据')
      }
      this.modifyBarlineData()
    },
    /**
     * @msg: k线图右键点击点击点操作
     * @param {type}
     * @return:
     */
    candlestickContextMenukHandle(params = {}, type) {
      const {
        data: { name }
      } = params
      const days = dayjs(this.defaultDate).diff(dayjs(name), 'day')
      if (type === 'index') {
        this.indexFormData.days = days
        this.indexModelFlag = true
      } else if (type === 'xbsj') {
        this.xbwlsjFormData.days = days
        this.xbwlsjModelFlag = true
      }
    },
    /**
     * description: k线图点击
     * param {type}
     * return: void
     */
    candlestickClickHandle(params = {}) {
      const {
        data: { name, type }
      } = params
      if (!type) return
      this.currentMonth = name
      const { currentMeterId } = this
      // k线图能进行滚动缩放，表示已经进入具体某天，因此可以进行滚动缩放请求。
      if (this.indexFlag !== 'day' && this.currentKxianReqIndexType !== 'day') {
        // 指数选择后进入最后一层，显示返回按钮
        this.showKxianBackBtn = true
        this.indexHasCandlestickDatezoom = true
        this.currentKxianReqIndexType = 'day'
        this.fetcKxianDaysData({
          meterId: currentMeterId,
          type,
          date: name
        })
      }
    },
    /**
     * @msg: 指数类型修改
     * @param {type}
     * @return:
     */
    changeIndexFlagHandle(val) {
      if (!val) return
      const { currentMeterId } = this
      if (!currentMeterId) {
        this.indexFlag = 'day'
        return this.showWraningNotice('', '请选择数据后再操作')
      }
      this.currentKxianReqIndexType = val
      if (val === 'day') {
        this.showKxianBackBtn = false
        this.indexHasCandlestickDatezoom = true
        this.currentMonth = this.defaultDate
      } else {
        this.indexHasCandlestickDatezoom = false
      }
      this.fetchDataByIndexType({
        meterId: currentMeterId,
        type: this.indexFlag
      })
    },
    /**
     * description: 指数类型（日、周、月）修改，获取新的k线图数据
     * param {type}
     * return: void
     */
    fetchDataByIndexType(params) {
      this.kxianSpinLoading = true
      kxianDataByIndexType(params).then(res => {
        this.kxianSpinLoading = false
        if (res.date) {
          const retArr = []
          each(res.date, item => {
            retArr.push(item[0])
          })
          this.datezoomRangeByIndex = retArr
          const { categoryData, values = {}, actualGas } = this.modifyKxianData(res.date, this.indexFlag)
          this.candlestickData = {
            categoryData,
            values,
            actualGas
          }
        }
      })
    },
    /**
     * description: 点击k线图请求数据
     * param {type}
     * return: void
     */
    fetcKxianDaysData(params = {}, type) {
      this.kxianSpinLoading = true
      kxianDataByDys(params).then(res => {
        this.kxianSpinLoading = false
        if (res.date) {
          if (type === 'zoom') {
            this.filterCandlestickData(res.date)
          } else {
            const { categoryData, values = {}, actualGas } = this.modifyKxianData(res.date, this.indexFlag)
            this.candlestickData = {
              categoryData,
              values,
              actualGas
            }
          }
        }
      })
    },
    /**
     * description: 点击返回重新请求k线图数据
     * param {type}
     * return:
     */
    kxianBackHandle() {
      this.currentKxianReqIndexType = this.indexFlag
      this.indexHasCandlestickDatezoom = false
      const { currentMeterId } = this
      this.fetchDataByIndexType({
        meterId: currentMeterId,
        type: this.indexFlag
      })
      this.showKxianBackBtn = false
    },
    /**
     * @msg: 从已保存的数据中筛选已设置的数据
     * @param {type}
     * @return: null || 设置好的markData
     */
    filterMarkData() {
      const retData = this.resultSubmitData
      const len = retData.length
      const { currentMeterId } = this
      let retMarkData = null
      for (let i = 0; i < len; i++) {
        if (currentMeterId === retData[i].meterId) {
          const { startValue, endValue, start, end } = retData[i]
          retMarkData = [
            {
              ...markItemStyle,
              type: 'min',
              index: start - 1,
              name: '开始',
              coord: [start - 1, startValue],
              value: startValue,
              hour: start
            },
            {
              ...markItemStyle,
              type: 'max',
              index: end - 1,
              name: '结束',
              coord: [end - 1, endValue],
              value: endValue,
              hour: end
            }
          ]
          break
        }
      }
      return retMarkData
    },
    /**
     * @msg: 设置起始和结束
     * @param {type}
     * @return:
     */
    zhexianContextMenuSelectHandle(data, type) {
      if (type === 'cancel') {
        return this.zhexianContextMenuCancelHandle(data)
      }
      let value = 0
      const { index } = data
      value = data.value
      if (isArray(data.value)) {
        value = data.value[1]
      }
      const markDataLen = this.currentMarkData.length
      const currentArr = cloneDeep(this.currentMarkData)
      if (markDataLen < 2) {
        if (markDataLen === 0 && type === 'min') {
          currentArr.push({
            ...data,
            ...markItemStyle,
            type,
            index,
            value,
            name: '开始',
            coord: [index, value]
          })
        } else if (markDataLen === 0 && type === 'max') {
          currentArr.push({
            ...data,
            ...markItemStyle,
            type,
            index,
            value,
            name: '结束',
            coord: [index, value]
          })
        } else {
          const firstData = currentArr[0]
          if (type === firstData.type) {
            return this.showWraningNotice('', '同类型点已存在')
          }
          if (index === firstData.xAxis) {
            return this.showWraningNotice('', '同一个点不能重复设置')
          }
          if ((type === 'max' && index < firstData.index) || (type === 'min' && index > firstData.index)) {
            return this.showWraningNotice('', '起始不能小于结束')
          }
          if (index >= firstData.index) {
            currentArr.push({
              ...data,
              ...markItemStyle,
              type,
              index,
              value,
              name: '结束',
              coord: [index, value]
            })
          } else {
            currentArr.unshift({
              ...data,
              ...markItemStyle,
              type,
              index,
              value,
              name: '开始',
              coord: [index, value]
            })
          }
        }

        this.currentMarkData = currentArr
      } else {
        this.showWraningNotice('', '起始数据和结束数据已存在不能再添加')
      }
    },
    /**
     * @msg: 取消设置
     * @param {type}
     * @return:
     */
    zhexianContextMenuCancelHandle(data) {
      const { value, index } = data
      const oldData = cloneDeep(this.currentMarkData)
      const num = findIndex(oldData, o => {
        return o.value === value && o.index === index
      })
      if (num >= 0) {
        oldData.splice(num, 1)
      }
      this.currentMarkData = oldData
    },
    /**
     * @msg: 天数折线图点击
     * @param {type}
     * @return:
     */
    zhexianDayClickHandle(params = {}) {
      const { data = {} } = params
      const { hour } = data

      this.getMeterDetailByTime(hour)
    },
    /**
     * @msg: 保存数据
     * @param {type}
     * @return:
     */
    saveData() {
      const len = this.currentMarkData.length
      if (!len) {
        this.showWraningNotice('', '没有可保存的数据')
      } else if (len === 1) {
        this.showWraningNotice('', '数据不完整，必须同时设置起始和结束')
      } else {
        const { currentMeterId } = this
        const [startData, endData] = this.currentMarkData
        const data = {
          meterId: currentMeterId,
          tId: this.defaultDate,
          start: startData.hour,
          end: endData.hour,
          startValue: startData.value,
          endValue: endData.value
        }
        this.resultSubmitData.push(data)
        this.$Message.success('保存成功')
      }
    },
    /**
     * @msg: 数据提交
     * @param {type}
     * @return:
     */
    submitData() {
      const len = this.resultSubmitData.length
      if (!len) {
        this.showWraningNotice('', '没有可提交的数据')
      } else {
        submitData(this.resultSubmitData)
          .then(res => {
            this.$Message.success(res.msg)
          })
          .catch(e => {
            this.$Message.error('提交失败')
          })
      }
    }
  }
}
</script>
<style lang="less" scoped>
@import './index.less';
</style>
